﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Media;
using System.Text;
using System.Windows.Controls;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Markup;
using AircraftBattleServer;
using System.Windows.Media.Animation;

namespace AircraftBattleClient
{
    public enum Direction
    {
        Up,
        Down,
        Left,
        Right
    };

    public class BattleLib
    {
        static private SoundPlayer sndFire = new SoundPlayer(Constants.SoundFolderRelativePath
                + "\\" + "WraithFire.wav");
        static private SoundPlayer sndDestroy = new SoundPlayer(Constants.SoundFolderRelativePath
                + "\\" + "WraithDestroyed.wav");

        static public void SetPosition(UIElement element, double x, double y)
        {
            Canvas.SetLeft(element, x);//Canvas function is the game background function.
            Canvas.SetTop(element, y);
        }

        static public double RotateImageToPoint(Image img, Point p, double offset = 0)
        {
            double width = img.Width;
            double height = img.Height;
            Point center = new Point();

            center.X = Canvas.GetLeft(img) + width / 2;
            center.Y = Canvas.GetTop(img) + height / 2;

            double rotate = Math.Atan2(p.Y - center.Y, p.X - center.X) * 180 / Math.PI;
            rotate -= offset; //Adjust this according to the aircraft's initial direction

            TransformGroup group = new TransformGroup();
            TranslateTransform t1 = new TranslateTransform(-width / 2, -height / 2);
            RotateTransform r = new RotateTransform(rotate);
            TranslateTransform t2 = new TranslateTransform(width / 2, height / 2);

            group.Children.Add(t1);
            group.Children.Add(r);
            group.Children.Add(t2);

            img.RenderTransform = group;

            return rotate + offset;
        }

        static public void RotateImage(Image img, double angle)
        {
            double width = img.Width;
            double height = img.Height;

            TransformGroup group = new TransformGroup();
            TranslateTransform t1 = new TranslateTransform(-width / 2, -height / 2);
            RotateTransform r = new RotateTransform(angle);
            TranslateTransform t2 = new TranslateTransform(width / 2, height / 2);

            group.Children.Add(t1);
            group.Children.Add(r);
            group.Children.Add(t2);

            img.RenderTransform = group;
        }

        static public Image CreateAircraftImage(
            FrameworkElement parent, int id, int team, double x = 0, double y = 0)
        {
            if (team == 1)
                return CreateImage(parent, ClientUtility.GetAircraftImageName(id),
                    Constants.Aircraft1ImageName, Constants.AircraftImageWidth,
                    Constants.AircraftImageHeight, x, y);
            else
                return CreateImage(parent, ClientUtility.GetAircraftImageName(id),
                    Constants.Aircraft2ImageName, Constants.AircraftImageWidth,
                    Constants.AircraftImageHeight, x, y);
        }

        static public Image CreateMissileImage
            (FrameworkElement parent, string id, MyPoint position)
        {
            return CreateMissileImage(parent, id, position.x, position.y);
        }

        static public Image CreateMissileImage(FrameworkElement parent, string id, double x = 0, double y = 0)
        {
            sndFire.Play();
            return CreateImage(parent,
                ClientUtility.GetMissileImageName(id),
                Constants.Missile1ImageName);
        }

        /// <summary>
        /// Create a WPF image control from disk image file
        /// </summary>
        static public Image CreateImage(FrameworkElement parent,
            string name, string picname, double width = 0, double height = 0, double x = 0, double y = 0)
        {

            Image img = new Image();

            // Read image file into a BitmapImage object
            BitmapImage bi = new BitmapImage();
            bi.BeginInit();
            bi.UriSource = new Uri(Constants.ImageFolderRelativePath
                + "\\" + picname, UriKind.Relative);
            bi.EndInit();

            // Set the source of the WPF image to the generated
            // BitmapImage object
            img.Source = bi;
            img.Width = (width > 0) ? width : bi.Width;
            img.Height = (height > 0) ? height : bi.Height;
            img.Name = name;

            // Add the image to its parent
            ((IAddChild)parent).AddChild(img);
            parent.RegisterName(name, img);

            // Set the position of the image.
            SetPosition(img, x, y);

            return img;
        }


        static public Image CreateImage(FrameworkElement parent,
            string picname, double width = 0, double height = 0, double x = 0, double y = 0)
        {
            Image img = new Image();
            BitmapImage bi = new BitmapImage();
            bi.BeginInit();
            bi.UriSource = new Uri(Constants.ImageFolderRelativePath
                + "\\" + picname, UriKind.Relative);
            bi.EndInit();
            img.Source = bi;
            img.Width = (width > 0) ? width : bi.Width;
            img.Height = (height > 0) ? height : bi.Height;

            ((IAddChild)parent).AddChild(img);

            SetPosition(img, x, y);
            return img;
        }

        public static MyPoint ChangeAircraftPosition(
            UIElement img, int craftId, Direction direction)
        {
            double x = Canvas.GetLeft(img);
            double y = Canvas.GetTop(img);

            switch (direction)
            {
                case Direction.Down:
                    y += Constants.MovementOneStepLength;
                    break;
                case Direction.Up:
                    y -= Constants.MovementOneStepLength;
                    break;
                case Direction.Left:
                    x -= Constants.MovementOneStepLength;
                    break;
                case Direction.Right:
                    x += Constants.MovementOneStepLength;
                    break;
                default:
                    break;
            }

            BattleLib.SetPosition(img, x, y);
            return new MyPoint() { x = x, y = y };
        }


        internal static void Die(Canvas canvas, Aircraft ac)
        {
            MyPoint p = ac.position;
            sndDestroy.Play();
            Image img = (Image)canvas.FindName(ClientUtility.GetAircraftImageName(ac.id));
            if (img == null) return;
            SetPosition(img, -100, -100);// This means to set the aircraft out of the background after it dies in order to speed the process.
            canvas.Children.Remove(img);
            
            // Display explosion animation
            PlayExplosionAnimation(canvas, p);
        }

        private static void PlayExplosionAnimation(FrameworkElement parent, MyPoint p)
        {
            // parent is the framework to play the exlosion image.
            Image img = CreateImage(parent, Constants.ExplosionImagename,
                Constants.AircraftImageWidth + 6, Constants.AircraftImageHeight + 6, p.x, p.y);

            DoubleAnimation myDoubleAnimation1 = new DoubleAnimation();
            myDoubleAnimation1.From = img.Width;
            myDoubleAnimation1.To = 0;
            myDoubleAnimation1.BeginTime = TimeSpan.FromSeconds(0);
            myDoubleAnimation1.Duration = new Duration(TimeSpan.FromSeconds(0.5));
            myDoubleAnimation1.AutoReverse = false;

            DoubleAnimation myDoubleAnimation2 = new DoubleAnimation();
            myDoubleAnimation2.From = img.Height;
            myDoubleAnimation2.To = 0;
            myDoubleAnimation2.BeginTime = TimeSpan.FromSeconds(0);
            myDoubleAnimation2.Duration = new Duration(TimeSpan.FromSeconds(0.5));
            myDoubleAnimation2.AutoReverse = false;

            Storyboard myStoryboard = new Storyboard();

            myStoryboard.Children.Add(myDoubleAnimation1);// This is the way to change explosion image bigger when explosion begins.
            Storyboard.SetTarget(myDoubleAnimation1, img);
            Storyboard.SetTargetProperty(myDoubleAnimation1, new PropertyPath(Image.WidthProperty));

            myStoryboard.Children.Add(myDoubleAnimation2);
            Storyboard.SetTarget(myDoubleAnimation2, img);
            Storyboard.SetTargetProperty(myDoubleAnimation2, new PropertyPath(Image.HeightProperty));

            myStoryboard.Begin(parent);
        }

        internal static bool MinimunShootingIntervalPassed(DateTime dateTime)
        {
            TimeSpan ts = DateTime.Now - dateTime;
            return ts.TotalMilliseconds > Constants.ShootingMinimunInterval;
        }
    }
}
